{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 描述\n",
    "`sort()` 函数用于对原列表进行排序，如果指定参数，则使用比较函数指定的比较函数。\n",
    "\n",
    "# 语法\n",
    "`sort()` 方法语法：\n",
    "\n",
    "`list.sort( key=None, reverse=False)`\n",
    "\n",
    "# 参数\n",
    "`key` -- 主要是用来进行比较的元素，只有一个参数，具体的函数的参数就是取自于可迭代对象中，指定可迭代对象中的一个元素来进行排序。\n",
    "`reverse` -- 排序规则，`reverse = True` 降序， `reverse = False` 升序（默认）。\n",
    "\n",
    "# 返回值\n",
    "该方法没有返回值，但是会对列表的对象进行排序。\n",
    "\n",
    "# 实例\n",
    "以下实例展示了 `sort()` 函数的使用方法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "List :  ['Facebook', 'Google', 'Runoob', 'Taobao']\n"
     ]
    }
   ],
   "source": [
    "#!/usr/bin/python\n",
    " \n",
    "aList = ['Google', 'Runoob', 'Taobao', 'Facebook']\n",
    " \n",
    "aList.sort()\n",
    "print ( \"List : \", aList)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "以下实例降序输出列表："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "降序输出: ['u', 'o', 'i', 'e', 'a']\n"
     ]
    }
   ],
   "source": [
    "#!/usr/bin/python\n",
    "# -*- coding: UTF-8 -*-\n",
    " \n",
    "# 列表\n",
    "vowels = ['e', 'a', 'u', 'o', 'i']\n",
    " \n",
    "# 降序\n",
    "vowels.sort(reverse=True)\n",
    " \n",
    "# 输出结果\n",
    "print ( '降序输出:', vowels )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "以下实例演示了通过指定列表中的元素排序来输出列表："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "排序列表： [(4, 1), (2, 2), (1, 3), (3, 4)]\n"
     ]
    }
   ],
   "source": [
    "#!/usr/bin/python\n",
    " \n",
    "# 获取列表的第二个元素\n",
    "def takeSecond(elem):\n",
    "    return elem[1]\n",
    " \n",
    "# 列表\n",
    "random = [(2, 2), (3, 4), (4, 1), (1, 3)]\n",
    " \n",
    "# 指定第二个元素排序\n",
    "random.sort(key=takeSecond)\n",
    " \n",
    "# 输出类别\n",
    "print ('排序列表：', random)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('a', 2), ('b', 3), ('c', 1), ('d', 4)]"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 示例：创建由元组构成的列表：\n",
    "a = [('b',3), ('a',2), ('d',4), ('c',1)]\n",
    "\n",
    "# 按照第一个元素排序\n",
    "sorted(a, key=lambda x:x[0])\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[('c', 1), ('a', 2), ('b', 3), ('d', 4)]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 按照第二个元素排序          \n",
    "sorted(a, key=lambda x:x[1])\n",
    "\n",
    "# key = lambda x:x[?] 是固定写法，x其实可以为任意值。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# key参数很妙\n",
    "key参数是一个很棒的设计。能把事情变得简单高效。说它简单是因为只需要提供一个单参数函数来提取或者计算一个值作为比较大小的标准即可，在排序的时候，python会基于两个key，但是那一阶段的计算发生在C语言那一层，这样会比调用用户自定义的python比较函数更快。\n",
    "因此用sorted函数效率更高。\n",
    "\n",
    "# 用法举例\n",
    "下面这个代码是对一副扑克牌进行排序。\n",
    "\n",
    "扑克牌有两个属性，一个是rank，一个是花色（suits）。\n",
    "- 首先自己定义init方法来初始化扑克牌\n",
    "- 然后自己定义len方法来计算扑克牌的长度\n",
    "- 然后自己定义getitem方法来返回下标，这样可以最大情况下避免重造轮子\n",
    "\n",
    "定义了排序函数`spades_high`，根据扑克牌的`rank`和`suit`来确定返回的`key`，然后使用`sorted`进行排序，返回一个python的迭代器。\n",
    "\n",
    "从结果中可以看到，扑克牌顺序输出。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Card(rank='7', suit='diamond')\n",
      "[Card(rank='2', suit='spades'), Card(rank='3', suit='spades'), Card(rank='4', suit='spades'), Card(rank='5', suit='spades'), Card(rank='6', suit='spades'), Card(rank='7', suit='spades'), Card(rank='8', suit='spades'), Card(rank='9', suit='spades'), Card(rank='10', suit='spades'), Card(rank='J', suit='spades'), Card(rank='Q', suit='spades'), Card(rank='K', suit='spades'), Card(rank='A', suit='spades'), Card(rank='2', suit='diamonds'), Card(rank='3', suit='diamonds'), Card(rank='4', suit='diamonds'), Card(rank='5', suit='diamonds'), Card(rank='6', suit='diamonds'), Card(rank='7', suit='diamonds'), Card(rank='8', suit='diamonds'), Card(rank='9', suit='diamonds'), Card(rank='10', suit='diamonds'), Card(rank='J', suit='diamonds'), Card(rank='Q', suit='diamonds'), Card(rank='K', suit='diamonds'), Card(rank='A', suit='diamonds'), Card(rank='2', suit='clubs'), Card(rank='3', suit='clubs'), Card(rank='4', suit='clubs'), Card(rank='5', suit='clubs'), Card(rank='6', suit='clubs'), Card(rank='7', suit='clubs'), Card(rank='8', suit='clubs'), Card(rank='9', suit='clubs'), Card(rank='10', suit='clubs'), Card(rank='J', suit='clubs'), Card(rank='Q', suit='clubs'), Card(rank='K', suit='clubs'), Card(rank='A', suit='clubs'), Card(rank='2', suit='hearts'), Card(rank='3', suit='hearts'), Card(rank='4', suit='hearts'), Card(rank='5', suit='hearts'), Card(rank='6', suit='hearts'), Card(rank='7', suit='hearts'), Card(rank='8', suit='hearts'), Card(rank='9', suit='hearts'), Card(rank='10', suit='hearts'), Card(rank='J', suit='hearts'), Card(rank='Q', suit='hearts'), Card(rank='K', suit='hearts'), Card(rank='A', suit='hearts')]\n",
      "52\n",
      "Card(rank='2', suit='spades')\n",
      "Card(rank='A', suit='hearts')\n",
      "Card(rank='5', suit='hearts')\n",
      "Card(rank='8', suit='clubs')\n",
      "**************************************************\n",
      "Card(rank='2', suit='clubs')\n",
      "Card(rank='2', suit='diamonds')\n",
      "Card(rank='2', suit='hearts')\n",
      "Card(rank='2', suit='spades')\n",
      "Card(rank='3', suit='clubs')\n",
      "Card(rank='3', suit='diamonds')\n",
      "Card(rank='3', suit='hearts')\n",
      "Card(rank='3', suit='spades')\n",
      "Card(rank='4', suit='clubs')\n",
      "Card(rank='4', suit='diamonds')\n",
      "Card(rank='4', suit='hearts')\n",
      "Card(rank='4', suit='spades')\n",
      "Card(rank='5', suit='clubs')\n",
      "Card(rank='5', suit='diamonds')\n",
      "Card(rank='5', suit='hearts')\n",
      "Card(rank='5', suit='spades')\n",
      "Card(rank='6', suit='clubs')\n",
      "Card(rank='6', suit='diamonds')\n",
      "Card(rank='6', suit='hearts')\n",
      "Card(rank='6', suit='spades')\n",
      "Card(rank='7', suit='clubs')\n",
      "Card(rank='7', suit='diamonds')\n",
      "Card(rank='7', suit='hearts')\n",
      "Card(rank='7', suit='spades')\n",
      "Card(rank='8', suit='clubs')\n",
      "Card(rank='8', suit='diamonds')\n",
      "Card(rank='8', suit='hearts')\n",
      "Card(rank='8', suit='spades')\n",
      "Card(rank='9', suit='clubs')\n",
      "Card(rank='9', suit='diamonds')\n",
      "Card(rank='9', suit='hearts')\n",
      "Card(rank='9', suit='spades')\n",
      "Card(rank='10', suit='clubs')\n",
      "Card(rank='10', suit='diamonds')\n",
      "Card(rank='10', suit='hearts')\n",
      "Card(rank='10', suit='spades')\n",
      "Card(rank='J', suit='clubs')\n",
      "Card(rank='J', suit='diamonds')\n",
      "Card(rank='J', suit='hearts')\n",
      "Card(rank='J', suit='spades')\n",
      "Card(rank='Q', suit='clubs')\n",
      "Card(rank='Q', suit='diamonds')\n",
      "Card(rank='Q', suit='hearts')\n",
      "Card(rank='Q', suit='spades')\n",
      "Card(rank='K', suit='clubs')\n",
      "Card(rank='K', suit='diamonds')\n",
      "Card(rank='K', suit='hearts')\n",
      "Card(rank='K', suit='spades')\n",
      "Card(rank='A', suit='clubs')\n",
      "Card(rank='A', suit='diamonds')\n",
      "Card(rank='A', suit='hearts')\n",
      "Card(rank='A', suit='spades')\n"
     ]
    }
   ],
   "source": [
    "import collections\n",
    "from random import choice\n",
    "\n",
    "Card = collections.namedtuple('Card', ['rank', 'suit'])   #定义类型card，有rank和card两种属性\n",
    "\n",
    "class FrenchDeck:\n",
    "    ranks = [str(n) for n in range(2, 11)] + list('JQKA')\n",
    "    suits = 'spades diamonds clubs hearts'.split()\n",
    "\n",
    "    def __init__(self):\n",
    "        self.cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]\n",
    "\n",
    "    def __len__(self):\n",
    "        return len(self.cards)\n",
    "\n",
    "    def __getitem__(self, position):\n",
    "        return self.cards[position]\n",
    "beer_card = Card('7', 'diamond')\n",
    "print(beer_card)\n",
    "french = FrenchDeck()\n",
    "print(french.cards)\n",
    "print(len(french))\n",
    "print(french[0])\n",
    "print(french[-1])\n",
    "print(choice(french))\n",
    "print(choice(french))\n",
    "\n",
    "print('*'*50)\n",
    "\n",
    "#排序\n",
    "suit_valus = dict(spades = 3, hearts = 2, diamonds = 1, clubs = 0)\n",
    "def spades_high(card):   #排序函数，定义key，使得从低到高排序\n",
    "    rank_value = french.ranks.index(card.rank)\n",
    "    return rank_value * 4 + suit_valus[card.suit]\n",
    "for card in sorted(french, key=spades_high):\n",
    "    print(card)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
